﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using ERPStore.Extensions;

namespace ERPStore.Services
{
	public class SalesService : ISalesService
	{
		public SalesService()
		{
		}

		#region ISalesService Members

		public virtual ERPStore.Models.ISaleDocument CreateOrderFromCart(ERPStore.Models.User user, ERPStore.Models.OrderCart cart, string payementModeName)
		{
			throw new NotImplementedException();
		}

		public virtual ERPStore.Models.Order GetOrderByCode(string orderCode)
		{
			throw new NotImplementedException();
		}

		public virtual ERPStore.Models.Order GetOrderById(int orderId)
		{
			throw new NotImplementedException();
		}

		public virtual List<ERPStore.Models.Order> GetOrderList(ERPStore.Models.User user, ERPStore.Models.OrderListFilter filter, int pageIndex, int size, out int count)
		{
			throw new NotImplementedException();
		}

		public virtual Dictionary<int, string> GetPeriodFilterList()
		{
			throw new NotImplementedException();
		}

		public virtual Dictionary<int, string> GetQuoteStateList()
		{
			throw new NotImplementedException();
		}

		public virtual bool IsCancelableQuote(ERPStore.Models.ISaleDocument order)
		{
			throw new NotImplementedException();
		}

		public virtual void CancelQuote(ERPStore.Models.Quote quote, ERPStore.Models.CancelQuoteReason reason, string comment)
		{
			throw new NotImplementedException();
		}

		public virtual void AddCommentToOrder(ERPStore.Models.Order order, string comment)
		{
			throw new NotImplementedException();
		}

		public virtual ERPStore.Models.Price GetProductSalePrice(ERPStore.Models.Product product, ERPStore.Models.User user, int Quantity, out bool isCustomerPriceApplied)
		{
			throw new NotImplementedException();
		}

		public virtual void AddPaymentToOrder(ERPStore.Models.Order order, string paymentModeName, string transactionId, object message)
		{
			throw new NotImplementedException();
		}

		public virtual void AddPaymentToOrder(ERPStore.Models.Order order, string paymentModeName, string transactionId, object message, decimal amount)
		{
			throw new NotImplementedException();
		}

		public virtual ERPStore.Models.Order GetLastOrder(ERPStore.Models.User user)
		{
			throw new NotImplementedException();
		}

		public virtual ERPStore.Models.Quote GetQuoteById(int quoteId)
		{
			throw new NotImplementedException();
		}

		public virtual ERPStore.Models.Quote GetQuoteByCode(string code)
		{
			throw new NotImplementedException();
		}

		public virtual IEnumerable<ERPStore.Models.Quote> GetQuoteList(ERPStore.Models.User user, ERPStore.Models.QuoteListFilter filter, int pageIndex, int pageSize, out int count)
		{
			throw new NotImplementedException();
		}

		public virtual void AddCommentToQuote(ERPStore.Models.Quote quote, string comment)
		{
			throw new NotImplementedException();
		}

		public virtual ERPStore.Models.Order ConvertQuoteToOrder(ERPStore.Models.Quote quote, out List<string> warnings)
		{
			throw new NotImplementedException();
		}

		public virtual ERPStore.Models.OrderCart CreateOrderCartFromQuote(ERPStore.Models.Quote quote)
		{
			throw new NotImplementedException();
		}

		public virtual ERPStore.Models.WorkflowList GetWorkflow(ERPStore.Models.Order order)
		{
			throw new NotImplementedException();
		}

		public virtual ERPStore.Models.WorkflowList GetWorkflow(ERPStore.Models.Quote quote)
		{
			throw new NotImplementedException();
		}

		public virtual ERPStore.Models.WorkflowList GetWorkflow(ERPStore.Models.Invoice invoice)
		{
			throw new NotImplementedException();
		}

		public virtual ERPStore.Models.Invoice GetInvoiceByCode(string invoiceCode)
		{
			throw new NotImplementedException();
		}

		public virtual IEnumerable<ERPStore.Models.Invoice> GetInvoiceList(ERPStore.Models.User user, ERPStore.Models.InvoiceListFilter filter, int pageIndex, int pageSize, out int count)
		{
			throw new NotImplementedException();
		}

		public virtual List<ERPStore.Models.Payment> GetPaymentList()
		{
            var services = GlobalConfiguration.Configuration.DependencyResolver.GetServices<Services.IPaymentService>();

			var result = new List<ERPStore.Models.Payment>();
			foreach (var item in GlobalConfiguration.Configuration.Settings.Payment.AllowedPaymentList)
			{
				var service = services.SingleOrDefault(i => i.Name.Equals(item, StringComparison.InvariantCultureIgnoreCase));
				if (service == null)
				{
					// Le service indiqué n'est pas enregistré
					continue;
				}

				result.Add(new ERPStore.Models.Payment()
				{
					Name = item,
					ConfirmationRouteName = service.ConfirmationRouteName,
					ConfirmationViewName = service.ConfirmationViewName,
					FinalizedRouteName = service.FinalizedRouteName,
					FinalizedViewName = service.FinalizedViewName,
				});
			}

			return result;
		}

		public virtual List<ERPStore.Models.Payment> GetPaymentList(ERPStore.Models.OrderCart cart, ERPStore.Models.UserPrincipal principal)
		{
            var services = GlobalConfiguration.Configuration.DependencyResolver.GetServices<Services.IPaymentService>();

			var result = new List<ERPStore.Models.Payment>();
			foreach (var item in GlobalConfiguration.Configuration.Settings.Payment.AllowedPaymentList)
			{
				var service = services.SingleOrDefault(i => i.Name.Equals(item, StringComparison.InvariantCultureIgnoreCase));
				if (service == null)
				{
					// Le service indiqué n'est pas enregistré
					continue;
				}

				var allowed = service.IsAllowedFor(cart, principal);
				if (!allowed)
				{
					continue;
				}

				result.Add(new ERPStore.Models.Payment()
				{
					Name = item,
					IsSelected = cart.PaymentModeName != null 
									&& cart.PaymentModeName.Equals(item, StringComparison.InvariantCultureIgnoreCase),
					ConfirmationRouteName = service.ConfirmationRouteName,
					ConfirmationViewName = service.ConfirmationViewName,
					FinalizedRouteName = service.FinalizedRouteName,
					FinalizedViewName = service.FinalizedViewName,
				});
			}

			return result;
		}

		public virtual void CalculateShippingFee(ERPStore.Models.OrderCart cart, ERPStore.Models.UserPrincipal principal)
		{
			if (cart.ShippingFeeLocked)
			{
				return;
			}

			var user = principal.CurrentUser;

			var deliveryCountry = global::ERPStore.GlobalConfiguration.Configuration.Settings.Shipping.DeliveryCountryList.Single(i => i.Country == global::ERPStore.GlobalConfiguration.Configuration.Settings.Country);
			if (cart.DeliveryAddress != null)
			{
				deliveryCountry = global::ERPStore.GlobalConfiguration.Configuration.Settings.Shipping.DeliveryCountryList.FirstOrDefault(i => i.Country == cart.DeliveryAddress.Country);
			}
			else if (user != null)
			{
				var selectedCountry = user.DefaultAddress.Country;
				if (user.LastDeliveredAddress != null)
				{
					deliveryCountry = global::ERPStore.GlobalConfiguration.Configuration.Settings.Shipping.DeliveryCountryList.FirstOrDefault(i => i.Country == user.LastDeliveredAddress.Country);
				}
				else
				{
					deliveryCountry = global::ERPStore.GlobalConfiguration.Configuration.Settings.Shipping.DeliveryCountryList.FirstOrDefault(i => i.Country == selectedCountry);
				}
			}

			cart.FreeOfShippingAmount = deliveryCountry.MinimalFreeOfCarriageAmount;

			// Recherche du franco
			if (deliveryCountry.MinimalFreeOfCarriageAmount > 0
				&& cart.Total >= deliveryCountry.MinimalFreeOfCarriageAmount)
			{
				cart.ShippingFee = new ERPStore.Models.Fee();
				return;
			}

			// Dans le cas ou le tranporteur
			// n'a pas été encore affecté
			if (cart.Conveyor == null)
			{
				var accountService = GlobalConfiguration.Configuration.DependencyResolver.GetService<ERPStore.Services.IAccountService>();
				cart.Conveyor = accountService.GetDefaultConveyor();
			}

			var unitPriceByLevel = cart.Conveyor.UnitPriceByTransportLevel;

			// Calcul des frais de port pour chaque produit en tenant compte
			// des strategie liées aux produits
			var levelTotal = cart.Items.Sum(i => ERPStore.Extensions.ModelsExtensions.GetFeeTotal(i.Product.Shipping, i.Quantity, unitPriceByLevel));
			cart.ShippingFee = new ERPStore.Models.Fee()
			{
				Amount = Math.Max(levelTotal, deliveryCountry.ShippingFeeAmount),
				TaxRate = cart.GetShippingTaxRate(principal),
			};

		}

		public virtual void ProcessExport(ERPStore.Models.OrderCart cart, ERPStore.Models.UserPrincipal principal)
		{
			ERPStore.Models.DeliveryCountry shippingCountry = null;
			if (cart.DeliveryAddress != null)
			{
				shippingCountry = global::ERPStore.GlobalConfiguration.Configuration.Settings.Shipping.DeliveryCountryList.Single(i => i.Country == cart.DeliveryAddress.Country);
			}
			else if (principal.CurrentUser != null)
			{
				var country = global::ERPStore.GlobalConfiguration.Configuration.Settings.Country;
				if (principal.CurrentUser.Corporate != null)
				{
					country = principal.CurrentUser.DefaultAddress.Country;
				}
				shippingCountry = global::ERPStore.GlobalConfiguration.Configuration.Settings.Shipping.DeliveryCountryList.Single(i => i.Country == country);
			}

			if (shippingCountry != null)
			{
				foreach (var item in cart.Items)
				{
					item.SalePrice.TaxRate = shippingCountry.TaxRate / 100.0;
					if (item.RecyclePrice != null)
					{
						item.RecyclePrice.TaxRate = shippingCountry.TaxRate / 100.0;
						if (global::ERPStore.GlobalConfiguration.Configuration.Settings.Payment.DisableRecycleOnExport)
						{
							item.RecyclePrice.Value = 0;
						}
					}
				}
			}
		}

		public virtual ERPStore.Models.Quote UpdateQuoteFromCart(ERPStore.Models.User user, ERPStore.Models.OrderCart cart, IList<ERPStore.Models.ProductStockInfo> productStockInfoList)
		{
			throw new NotImplementedException();
		}

		public virtual IList<ERPStore.Models.Conveyor> GetConveyorList(ERPStore.Models.OrderCart cart)
		{
			throw new NotImplementedException();
		}

		public virtual void CancelOrder(Models.Order order, string reason)
		{
			throw new NotImplementedException();
		}

        public virtual string GetPaymentModeNameById(int paymentModeNameId)
        {
            throw new NotImplementedException();
        }

		public virtual Models.Delivery GetDeliveryById(int deliveryId)
		{
			throw new NotImplementedException();
		}

		public virtual Models.PriceHistory GetPriceHistory(Models.Product product, Models.User user)
		{
			throw new NotImplementedException();
		}

		public virtual IList<Models.PriceHistory> GetPriceHistoryList(List<int> productIdList, Models.User user)
		{
			throw new NotImplementedException();
		}

		public virtual void ApplyBestPrice(IList<Models.Product> productList, Models.User user)
		{
			// Do nothing
			foreach (var product in productList)
			{
				ApplyBestPrice(product, user);
			}
		}

		public virtual void ApplyBestPrice(Models.Product product, Models.User user)
		{
			if (product.BestPrice == null)
			{
				product.BestPrice = product.SalePrice;
			}
		}

		public virtual void SetOrderReceivedByCustomer(int orderId)
		{

		}

		public virtual IEnumerable<Models.ProductStats> GetProductStatListByIdList(IEnumerable<int> productIdList)
		{
			return null;
		}

		#endregion
	}
}
